package user

import (
	"context"
	"errors"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/errcode"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/repository/message/sms_code"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/repository/user"
	pb "git.mycaigou.com/gfyx/micro-gfyx-user-service/proto/micro_gfyx_user_service_proto/micro-gfyx-user-service"
	"git.myscrm.cn/golang/common/ykenv"
	"git.myscrm.cn/golang/common/ykerrcode"
	"git.myscrm.cn/golang/stark/v4"
	"github.com/google/uuid"
	"time"
)

const (
	// 登录类型：1-主应用PC；2-线索雷达小程序 3-单点登录（到pc）
	LOGINTYPE_PC     = 1
	LOGINTYPE_MINI   = 2
	LOGINTYPE_SSO_PC = 3
)

type UserLoginService struct {
	CommonUserLoginRecodeRepo user.CommonUserLoginRecodeRepoIface
	CommonUserBindRepo        user.CommonUserBindRepoIface
	CommonUserDataRepo        user.CommonUserDataRepoIface
	userInfoSerice            UserInfoServiceIface
	smsCodeRepo               sms_code.SmsCodeRepositoryIface
}

func NewUserLoginService(commonUserLoginRecodeRepo user.CommonUserLoginRecodeRepoIface, commonUserBindRepo user.CommonUserBindRepoIface,
	commonUserDataRepo user.CommonUserDataRepoIface,
	userInfoSerice UserInfoServiceIface,
	smsCodeRepo sms_code.SmsCodeRepositoryIface,
) UserLoginServiceIface {
	return &UserLoginService{
		CommonUserLoginRecodeRepo: commonUserLoginRecodeRepo,
		CommonUserBindRepo:        commonUserBindRepo,
		CommonUserDataRepo:        commonUserDataRepo,
		userInfoSerice:            userInfoSerice,
		smsCodeRepo:               smsCodeRepo,
	}
}

// 个人用户小程序注册逻辑
func (u *UserLoginService) PersonalUserMiniProgramRegister(ctx context.Context, mobile, openId string) (*user.CommonUserData, error) {
	commonUserData := &user.CommonUserData{
		Uid:           uuid.New().String(),
		TenantUserUid: "",
		MobilePhone:   mobile,
		TenantCode:    "",
		// todo
		UserName:    "",
		UserCode:    "",
		CreatedTime: time.Time{},
	}
	_, err := u.CommonUserDataRepo.Insert(ctx, commonUserData)
	if err != nil {
		return nil, err
	}
	return commonUserData, nil
}

func (u *UserLoginService) BindUser(ctx context.Context, mobile, openId string, wechatType int32, unionId string) (*user.CommonUserInfoBo, string, error) {

	commonUserInfoBo := &user.CommonUserInfoBo{}
	commonUserBindFailRecord := &user.CommonUserBindFailRecord{}
	commonUserBindFailRecord.MobilePhone = mobile
	commonUserBindFailRecord.Openid = openId
	commonUserBindFailRecord.WechatType = wechatType
	commonUserBindFailRecord.Unionid = unionId
	// 小程序绑定
	if wechatType == 1 {
		// 获取用户信息
		condition := make(map[string]interface{})
		condition["common_user_bind.mp_openid"] = openId
		commonUserInfoBo, err := u.CommonUserDataRepo.GetInfoWithBind(ctx, condition)
		if err != nil {
			commonUserBindFailRecord.FailMsg = err.Error()
			_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
			return commonUserInfoBo, "", err
		}
		// 判断openid和手机号（对应的用户全局uid）是否有最新绑定关系
		isHasLastOpenidAndMobileBindRelation := false
		// openid曾经绑定过
		if commonUserInfoBo.Uid != "" {
			if commonUserInfoBo.MobilePhone != mobile {
				// 最新的绑定关系中openid与手机号没关联
				isHasLastOpenidAndMobileBindRelation = false
				// 允许一个openid绑定多个手机号，也允许一个手机号绑定多个openid
				// 插入绑定失败记录
				//commonUserBindFailRecord.CommonUserDataUid = commonUserInfoBo.Uid
				//commonUserBindFailRecord.FailMsg = ykerrcode.GetErrMsg(errcode.USER_OPENID_ALREADY_BIND)
				//_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
				//return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_OPENID_ALREADY_BIND, ykerrcode.GetErrMsg(errcode.USER_OPENID_ALREADY_BIND))
			} else {
				// 最新的绑定关系中openid与手机号是关联，则无需调整绑定表
				isHasLastOpenidAndMobileBindRelation = true
			}
		} else {
			// openid从未绑定过
			isHasLastOpenidAndMobileBindRelation = false
		}
		// 最新绑定关系中，手机号和openid没关联的逻辑
		if isHasLastOpenidAndMobileBindRelation == false {
			// 查询用户数据是否存在,目前逻辑是手机号可能在多个租户中存在，则取最后更新时间的用户
			condition := make(map[string]interface{})
			condition["mobile_phone"] = mobile
			commonUserData, err := u.CommonUserDataRepo.GetInfo(ctx, condition, "modified_time desc")
			if err != nil {
				// 插入绑定失败记录
				commonUserBindFailRecord.FailMsg = err.Error()
				_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
				return commonUserInfoBo, "", err
			}
			commonUserBindFailRecord.CommonUserDataUid = commonUserData.Uid
			// 手机号不在用户库，则认为是个人用户（经销商，非租户用户）
			isPersonalUserMiniProgramRegister := false
			if commonUserData.MobilePhone == "" {
				// 经销商用户授权登录注册逻辑...
				isPersonalUserMiniProgramRegister = true
				commonUserData, err = u.PersonalUserMiniProgramRegister(ctx, mobile, openId)
				if err != nil {
					return commonUserInfoBo, "", err
				}
				//
				//// 插入绑定失败记录
				//commonUserBindFailRecord.FailMsg = ykerrcode.GetErrMsg(errcode.USER_BIND_MOBILE_NOT_EXISTS)
				//_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
				//return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_BIND_MOBILE_NOT_EXISTS, ykerrcode.GetErrMsg(errcode.USER_BIND_MOBILE_NOT_EXISTS))
			}
			// 租户级别用户的绑定判断逻辑
			if isPersonalUserMiniProgramRegister == false {
				if commonUserData.IsDisable == 1 {
					// 插入绑定失败记录
					commonUserBindFailRecord.FailMsg = ykerrcode.GetErrMsg(errcode.USER_BIND_DISABLED)
					_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
					return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_BIND_DISABLED, ykerrcode.GetErrMsg(errcode.USER_BIND_DISABLED))
				}
				//用户被绑定过，可以支持一个手机号绑定多个openid(微信号)

				// 判断用户是否被绑定过
				//condition2 := make(map[string]interface{})
				//condition2["common_user_data_uid"] = commonUserData.Uid
				//commonUserBind, err := u.CommonUserBindRepo.GetInfo(ctx, condition2)
				//if err != nil {
				//	return commonUserInfoBo, "", err
				//}
				//if commonUserBind.CommonUserDataUid != "" {
				//	// 插入绑定失败记录
				//	commonUserBindFailRecord.FailMsg = ykerrcode.GetErrMsg(errcode.USER_ALREADY_BIND)
				//	_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
				//	return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_ALREADY_BIND, ykerrcode.GetErrMsg(errcode.USER_ALREADY_BIND))
				//}
				//if commonUserBind.TenantUserUid == commonUserData.TenantUserUid {
				//	// 插入绑定失败记录
				//	commonUserBindFailRecord.FailMsg = ykerrcode.GetErrMsg(errcode.USER_ALREADY_BIND)
				//	_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
				//	return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_ALREADY_BIND, ykerrcode.GetErrMsg(errcode.USER_ALREADY_BIND))
				//}
			}

			// 绑定
			commonUserBind := &user.CommonUserBind{
				Uid:               uuid.New().String(),
				CommonUserDataUid: commonUserData.Uid,
				TenantUserUid:     commonUserData.TenantUserUid,
				Openid:            "",
				MpOpenid:          openId,
				Unionid:           unionId,
			}
			_, err = u.CommonUserBindRepo.Insert(ctx, commonUserBind)
			if err != nil {
				// 插入绑定失败记录
				commonUserBindFailRecord.FailMsg = err.Error()
				commonUserBindFailRecord.CommonUserDataUid = commonUserData.Uid
				_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
				return commonUserInfoBo, "", err
			}

			time.Sleep(1 * time.Second)
			//commonUserInfoBo.Uid = commonUserBind.CommonUserDataUid
			//commonUserInfoBo.TanantUserUid = commonUserData.TanantUserUid
			//commonUserInfoBo.MobilePhone = commonUserData.MobilePhone
			//commonUserInfoBo.TenantCode = commonUserData.TenantCode
			//commonUserInfoBo.UserName = commonUserData.UserName
			//commonUserInfoBo.UserCode = commonUserData.UserCode
			//commonUserInfoBo.Openid = ""
			//commonUserInfoBo.MpOpenid = openId
		}

		// 顺便做登录，插入后立刻查询是否有db主从延迟问题？
		commonUserInfoBo, token, err := u.LoginByOpenId(ctx, openId, 1, unionId)
		if err != nil {
			stark.Logger.Error(ctx, "BindUser LoginByOpenId err "+err.Error())
			return commonUserInfoBo, "", err
		}
		if commonUserInfoBo.TenantCode != "" {
			tenantName, err := u.userInfoSerice.GetTenantName(ctx, commonUserInfoBo.TenantCode, false)
			if err != nil {
				stark.Logger.Error(ctx, "BindUser GetTenantName err "+err.Error())
				// 插入绑定失败记录
				commonUserBindFailRecord.FailMsg = err.Error()
				_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
				return nil, "", err
			}
			commonUserInfoBo.TenantName = tenantName
		}
		return commonUserInfoBo, token, nil
	} else if wechatType == 2 {
		// 公众号绑定...

	}

	// 插入绑定失败记录
	commonUserBindFailRecord.FailMsg = ykerrcode.GetErrMsg(errcode.USER_BIND_ERROR)
	_, _ = u.CommonUserBindRepo.InsertFailRecord(ctx, commonUserBindFailRecord)
	return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_BIND_ERROR, ykerrcode.GetErrMsg(errcode.USER_BIND_ERROR))
}

func (u *UserLoginService) VerifyToken(ctx context.Context, token string) (*user.CommonUserInfoBo, error) {
	commonUserInfoBo := &user.CommonUserInfoBo{}
	commonUserLoginRecord, err := u.CommonUserLoginRecodeRepo.GetAvailableLoginRecode(ctx, token)
	if err != nil {
		return commonUserInfoBo, err
	}
	if commonUserLoginRecord.CommonUserDataUid == "" {
		return commonUserInfoBo, ykerrcode.TogRPCError(errcode.USER_NOT_LOGIN, ykerrcode.GetErrMsg(errcode.USER_NOT_LOGIN))
	}
	//小程序的登录
	if commonUserLoginRecord.LoginType == LOGINTYPE_MINI {
		// 登录态一周有效
		loginStateValidTimeMini := "-" + stark.Configer.(stark.ApolloConfigerIface).GetStringValue("login_state_valid_time_mini", "166h")
		duration, _ := time.ParseDuration(loginStateValidTimeMini)
		dateTime := time.Now().Add(duration)
		// createTime < 一周前的时间
		if commonUserLoginRecord.CreatedTime.Before(dateTime) {
			return commonUserInfoBo, ykerrcode.TogRPCError(errcode.USER_NOT_LOGIN, ykerrcode.GetErrMsg(errcode.USER_NOT_LOGIN))
		}
		//判断用户是否绑定 改为 判断用户是否存在。 因为手机号登录不需要绑定openid
		commonUserInfoBo, err = u.CommonUserDataRepo.GetInfoByUid(ctx, commonUserLoginRecord.CommonUserDataUid)
		if err != nil {
			return commonUserInfoBo, err
		}
		if commonUserInfoBo.Uid == "" {
			return commonUserInfoBo, ykerrcode.TogRPCError(ykerrcode.ACCESS_DENIED, "用户不存在，无法登录")
		}
	} else if commonUserLoginRecord.LoginType == LOGINTYPE_PC || commonUserLoginRecord.LoginType == LOGINTYPE_SSO_PC {
		// pc登录 或主应用单点登录
		dateTime := u.GetPcLoginValidTime()
		// createTime < 12个小时前的时间
		if commonUserLoginRecord.CreatedTime.Before(dateTime) {
			return commonUserInfoBo, ykerrcode.TogRPCError(errcode.USER_NOT_LOGIN, ykerrcode.GetErrMsg(errcode.USER_NOT_LOGIN))
		}
		commonUserInfoBo, err = u.CommonUserDataRepo.GetInfoByUid(ctx, commonUserLoginRecord.CommonUserDataUid)
		if err != nil {
			return commonUserInfoBo, err
		}
		if commonUserInfoBo.Uid == "" {
			return commonUserInfoBo, ykerrcode.TogRPCError(ykerrcode.ACCESS_DENIED, "用户不存在，无法登录")
		}
	} else {
		return commonUserInfoBo, ykerrcode.TogRPCError(ykerrcode.ACCESS_DENIED, "暂时不支持此登录类型")
	}

	if commonUserInfoBo.IsDisable == 1 {
		return commonUserInfoBo, ykerrcode.TogRPCError(errcode.USER_ALREADY_DISALBED, ykerrcode.GetErrMsg(errcode.USER_ALREADY_DISALBED))
	}

	tenantName, err := u.userInfoSerice.GetTenantName(ctx, commonUserInfoBo.TenantCode, false)
	if err != nil {
		return nil, err
	}
	commonUserInfoBo.TenantName = tenantName

	return commonUserInfoBo, nil
}

func (u *UserLoginService) LoginByOpenId(ctx context.Context, openId string, loginType int32, unionId string) (*user.CommonUserInfoBo, string, error) {
	commonUserLoginRecode := &user.CommonUserLoginRecord{}
	commonUserInfoBo := &user.CommonUserInfoBo{}

	if loginType == 1 {
		// 获取用户信息
		condition := make(map[string]interface{})
		condition["common_user_bind.mp_openid"] = openId
		commonUserInfoBo, err := u.CommonUserDataRepo.GetInfoWithBind(ctx, condition)
		if err != nil {
			return commonUserInfoBo, "", err
		}
		if commonUserInfoBo.IsDisable == 1 {
			return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_ALREADY_DISALBED, ykerrcode.GetErrMsg(errcode.USER_ALREADY_DISALBED))
		}
		if commonUserInfoBo.Uid == "" {
			return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_LOGIN_NOT_BIND, ykerrcode.GetErrMsg(errcode.USER_LOGIN_NOT_BIND))
		}
		// 更新unionId
		if commonUserInfoBo.MpUnionId == "" && unionId != "" {
			updateData := map[string]interface{}{
				"unionid": unionId,
			}
			updateCondition := map[string]interface{}{
				//"common_user_data_uid": commonUserInfoBo.Uid,
				"mp_openid": openId,
			}
			_, err = u.CommonUserBindRepo.Update(ctx, updateData, updateCondition)
			if err != nil {
				stark.Logger.Error(ctx, "更新union_id,err:", err.Error())
			}
		}

		// 写入登录记录
		commonUserLoginRecode.LoginType = LOGINTYPE_MINI
		commonUserLoginRecode.Uid = uuid.New().String()
		commonUserLoginRecode.CommonUserDataUid = commonUserInfoBo.Uid
		commonUserLoginRecode.TenantUserUid = commonUserInfoBo.TenantUserUid
		commonUserLoginRecode.Token = uuid.New().String()
		_, err = u.CommonUserLoginRecodeRepo.Insert(ctx, commonUserLoginRecode)
		if err != nil {
			return commonUserInfoBo, "", err
		}
		tenantName, err := u.userInfoSerice.GetTenantName(ctx, commonUserInfoBo.TenantCode, false)
		if err != nil {
			return nil, "", err
		}
		commonUserInfoBo.TenantName = tenantName
		return commonUserInfoBo, commonUserLoginRecode.Token, nil
	} else if loginType == 2 {
		// 公众号登录....
	}
	return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_LOGIN_ERROR, ykerrcode.GetErrMsg(errcode.USER_LOGIN_ERROR))
}

// 通过账号密码登录
func (u *UserLoginService) LoginByAccountPassword(ctx context.Context, tenantCode, account, password string, isNeedMd5 bool) (*user.CommonUserInfoBo, string, error) {
	commonUserLoginRecode := &user.CommonUserLoginRecord{}
	commonUserInfoBo := &user.CommonUserInfoBo{}
	// 获取用户信息
	commonUserInfoBo, err := u.CommonUserDataRepo.GetInfoByAccountAndPassword(ctx, tenantCode, account, password, isNeedMd5)
	if err != nil {
		return commonUserInfoBo, "", err
	}
	if commonUserInfoBo.IsDisable == 1 {
		return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_ALREADY_DISALBED, ykerrcode.GetErrMsg(errcode.USER_ALREADY_DISALBED))
	}
	if commonUserInfoBo.Uid == "" {
		stark.Logger.Error(ctx, ykerrcode.GetErrMsg(errcode.USER_LOGIN_ERROR)+" 可能账号密码错误")
		return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_LOGIN_ERROR, ykerrcode.GetErrMsg(errcode.USER_LOGIN_ERROR))
	}
	// 写入登录记录表
	commonUserLoginRecode.LoginType = LOGINTYPE_PC
	commonUserLoginRecode.Uid = uuid.New().String()
	commonUserLoginRecode.CommonUserDataUid = commonUserInfoBo.Uid
	commonUserLoginRecode.TenantUserUid = commonUserInfoBo.TenantUserUid
	commonUserLoginRecode.Token = uuid.New().String()
	_, err = u.CommonUserLoginRecodeRepo.Insert(ctx, commonUserLoginRecode)
	if err != nil {
		return commonUserInfoBo, "", err
	}
	return commonUserInfoBo, commonUserLoginRecode.Token, nil
}

func (u *UserLoginService) Logout(ctx context.Context, globalUserId string, logoutType string) error {

	// 获取用户信息
	commonUserInfoBo, err := u.CommonUserDataRepo.GetInfoByUid(ctx, globalUserId)
	if err != nil {
		return err
	}
	if commonUserInfoBo == nil || commonUserInfoBo.Uid == "" {
		return errors.New("用户不存在：" + globalUserId)
	}
	_, err = u.CommonUserLoginRecodeRepo.Logout(ctx, globalUserId, logoutType)
	// todo 考虑子系统的退登？
	if err != nil {
		return err
	}
	return nil
}

func (u *UserLoginService) LogoutByToken(ctx context.Context, token string) error {
	return u.CommonUserLoginRecodeRepo.LogoutByToken(ctx, token)
}

func (u *UserLoginService) LoginBySso(ctx context.Context, tenantCode, account, appid string) (*user.CommonUserInfoBo, string, error) {
	// 获取用户信息
	condition := make(map[string]interface{})
	condition["tenant_code"] = tenantCode
	condition["user_code"] = account
	commonUserInfoBo, err := u.CommonUserDataRepo.GetInfoByAccount(ctx, tenantCode, account)
	if err != nil {
		return commonUserInfoBo, "", err
	}
	if commonUserInfoBo.IsDisable == 1 {
		return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_ALREADY_DISALBED, ykerrcode.GetErrMsg(errcode.USER_ALREADY_DISALBED))
	}
	if commonUserInfoBo.Uid == "" {
		return commonUserInfoBo, "", ykerrcode.TogRPCError(errcode.USER_LOGIN_ERROR, ykerrcode.GetErrMsg(errcode.USER_LOGIN_ERROR)+"，用户不存在")
	}

	// 判断是否存在
	condition2 := make(map[string]interface{})
	condition2["common_user_data_uid"] = commonUserInfoBo.Uid
	condition2["is_deleted"] = 0
	condition2["login_type"] = LOGINTYPE_SSO_PC
	condition2["appid"] = appid
	commonUserLoginRecode, err := u.CommonUserLoginRecodeRepo.GetInfo(ctx, condition2)
	if err != nil {
		return commonUserInfoBo, "", err
	}
	if commonUserLoginRecode != nil && commonUserLoginRecode.Uid != "" {
		// 更新单点登录记录
		updateDate := make(map[string]interface{})
		updateDate["created_time"] = time.Now()
		updateCondition := make(map[string]interface{})
		updateCondition["common_user_data_uid"] = commonUserLoginRecode.CommonUserDataUid
		updateCondition["login_type"] = LOGINTYPE_SSO_PC
		updateCondition["appid"] = appid
		pcLoginValidTime := u.GetPcLoginValidTime()
		duration, _ := time.ParseDuration("+1h")
		pcLoginValidTimeSubOne := pcLoginValidTime.Add(duration)
		// createTime < 离过期时间前1个小时的时间
		if commonUserLoginRecode.CreatedTime.Before(pcLoginValidTimeSubOne) {
			//刷新token
			updateDate["token"] = uuid.New().String()
			commonUserLoginRecode.Token = updateDate["token"].(string)
			//commonUserLoginRecode.CreatedTime = updateDate["created_time"].(time.Time)

		}
		_, err = u.CommonUserLoginRecodeRepo.Update(ctx, updateDate, updateCondition)
		if err != nil {
			return commonUserInfoBo, "", err
		}
	} else {
		// 插入登录记录
		commonUserLoginRecode.LoginType = LOGINTYPE_SSO_PC
		commonUserLoginRecode.Uid = uuid.New().String()
		commonUserLoginRecode.CommonUserDataUid = commonUserInfoBo.Uid
		commonUserLoginRecode.TenantUserUid = commonUserInfoBo.TenantUserUid
		commonUserLoginRecode.Token = uuid.New().String()
		commonUserLoginRecode.Appid = appid
		_, err = u.CommonUserLoginRecodeRepo.Insert(ctx, commonUserLoginRecode)
		if err != nil {
			return commonUserInfoBo, "", err
		}
	}
	return commonUserInfoBo, commonUserLoginRecode.Token, nil
}

// 获取pc登录有效时间
func (u *UserLoginService) GetPcLoginValidTime() time.Time {
	// 12小时有效
	loginStateValidTimePc := "-" + stark.Configer.(stark.ApolloConfigerIface).GetStringValue("login_state_valid_time_pc", "12h")
	duration, _ := time.ParseDuration(loginStateValidTimePc)
	dateTime := time.Now().Add(duration)
	return dateTime
}

/**
 *  @return 判断验证码是否正确：true 正确，false 不正确
 */

func (u *UserLoginService) equalCode(inputCode string, targetCode string) bool {
	if !ykenv.IsProdMode() {
		if inputCode == targetCode || inputCode == "123456" {
			return true
		} else {
			return false
		}
	}
	result := false
	if inputCode == targetCode {
		result = true
	}
	return result
}

// 短信验证码登录
func (u *UserLoginService) LoginByMobileSms(ctx context.Context, request *pb.LoginByMobileSmsRequest, loginType int32) (*user.CommonUserInfoBo, string, error) {
	//1、校验短信验证码
	smsCode, err := u.smsCodeRepo.GetCodeByMobile(ctx, request.Mobile, 0)
	if err != nil {
		stark.Logger.Error(ctx, "获取用户账号,err:%s", err.Error())
		return nil, "", err
	}

	if !ykenv.IsProdMode() && request.SmsCode == "123456" { //绿色通道

	} else if smsCode == nil || smsCode.Code == "" || request.SmsCode != smsCode.Code || utils.VerifyCodeExpire(smsCode.SendTime) {
		return nil, "", errors.New("验证码输入错误，请重新输入")
	}

	//2、获取租户账号，按最新创建时间排序，并登录
	userAccount, err := u.CommonUserDataRepo.GetUserInfoByMobileAndNotTenantCode(ctx, request.Mobile, "created_time desc")
	if err != nil {
		stark.Logger.Error(ctx, "获取用户账号,err:%s", err.Error())
	}
	if userAccount != nil && userAccount.Uid != "" { //按账号登录
		return u.LoginByAccountPassword(ctx, userAccount.TenantCode, userAccount.UserCode, userAccount.Password, false)
	}
	//3、获取非付费用户，存在则登录，不存在，先注册再登录
	commonUserData, err := u.CommonUserDataRepo.GetUserInfoByMobileNoPay(ctx, request.Mobile, "created_time desc")
	if commonUserData != nil && commonUserData.Uid == "" { //没有非付费账号
		commonUserData, err = u.PersonalUserMiniProgramRegister(ctx, request.Mobile, "")
		if err != nil {
			stark.Logger.Error(ctx, "创建非付费账号,err:%s", err.Error())
		}
	}
	// 写入登录记录
	commonUserInfoBo := &user.CommonUserInfoBo{}
	commonUserLoginRecode := &user.CommonUserLoginRecord{}
	if commonUserData != nil {
		commonUserLoginRecode.LoginType = LOGINTYPE_MINI
		commonUserLoginRecode.Uid = uuid.New().String()
		commonUserLoginRecode.CommonUserDataUid = commonUserData.Uid
		commonUserLoginRecode.TenantUserUid = commonUserData.TenantUserUid
		commonUserLoginRecode.Token = uuid.New().String()
		_, err = u.CommonUserLoginRecodeRepo.Insert(ctx, commonUserLoginRecode)
		if err != nil {
			return commonUserInfoBo, "", err
		}

		commonUserInfoBo.Uid = commonUserData.Uid
		commonUserInfoBo.MobilePhone = commonUserData.MobilePhone
		commonUserInfoBo.TenantUserId = commonUserData.TenantUserId
	}
	return commonUserInfoBo, commonUserLoginRecode.Token, nil

}
